#include "handy/handy/handy.h"
#include <cerrno>
#include <algorithm>
#include <stdio.h>
#include <string>
#include <stdint.h>
#include <arpa/inet.h>
#include "common.h"
#include "ikcp.h"
#include "xudp.pb.h"

using namespace std;
using namespace handy;

unsigned int g_id = 0;

string g_content;

ikcpcb* kcp;
UdpConnPtr con;
EventBase base;

int xkcp_output(const char *buf, int len, ikcpcb *kcp, void *user) {
	errno = 0;
	con->send(buf, len);
	if (errno != 0) {
		fatal("error:%d, msg:%s", errno, strerror(errno));
	}
	info("output:%d", len);
	return len;
}

void init_kcp() {
	kcp = ikcp_create(1, NULL);
	kcp->output = xkcp_output;
	ikcp_wndsize(kcp, 1000, 1000);
	ikcp_nodelay(kcp, 1, 10, 2, 1);
	kcp->rx_minrto = 10;
}

int main() {
	init_kcp();
	g_content = random_string(500);

	setloglevel("INFO");
  	setlogfile("test_client_kcp");

	Signal::signal(SIGINT, [&] { base.exit(); });
	con = UdpConn::createConnection(&base, SERVER_IP, SERVER_PORT);

	exitif(!con, "start udp conn failed");

	base.runAfter(0, [&]() {
		ikcp_update(kcp, (IUINT32)util::timeMilli());
	}, 2);

	con->onMsg([&](const UdpConnPtr& c, Buffer b) {
		char* data = b.data();
		int l = b.size();
		info("input:%d", l);
		ikcp_input(kcp, data, l);
	});
	
	char buf[1000]={};
	base.runAfter(0, [&]() {
		xmsg m;
		m.set_id(g_id++);
		m.set_buf(g_content.c_str(), MSG_SIZE);
		bool suc = m.SerializeToArray(buf, sizeof(buf));	
		if (!suc) {
			fatal("serialize failed!");
		}
		ikcp_send(kcp, buf, m.ByteSize());
		int wnd = ikcp_waitsnd(kcp);
		ikcp_flush(kcp);
	  	info("id:%d,time:%ld wnd:%d", m.id(),util::timeMilli(), wnd);	
		if(g_id > MAX_MSG_ID){
			base.exit();
		}

	}, MSG_INTERVAL);

	base.loop();
}
